#!/usr/bin/python
#
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
#
# Licensed to you under the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.  See the files README and
# LICENSE_GPL_v2 which accompany this distribution.
#

import os
import sys
import getopt
import signal
import getpass
import pwd
import grp
import threading
import logging
from logging import config as lconfig

from vdsm import constants
import zombieReaper
import dsaversion
if sys.version_info[0] == 2:
    # as long as we work with Python 2, we need to monkey-patch threading
    # module before it is ever used.
    import pthreading
    pthreading.monkey_patch()

loggerConfFile = constants.P_VDSM_CONF + 'logger.conf'


def usage():
    print "Usage:  vdsm [OPTIONS]"
    print "     -h  - Display this help message"


def serve_clients(log):
    cif = None

    def sigtermHandler(signum, frame):
        if cif:
            cif.prepareForShutdown()

    def sigusr1Handler(signum, frame):
        if cif and cif.irs:
            cif.irs.spmStop(
                cif.irs.getConnectedStoragePoolsList()['poollist'][0])

    signal.signal(signal.SIGTERM, sigtermHandler)
    signal.signal(signal.SIGUSR1, sigusr1Handler)
    zombieReaper.registerSignalHandler()

    from clientIF import clientIF  # must import after config is read
    cif = clientIF.getInstance(log)
    cif.serve()


def run():
    lconfig.fileConfig(loggerConfFile)
    logging.addLevelName(5, 'TRACE')
    logging.TRACE = 5  # impolite but helpful

    # Used to debug vdsm. on production machines
    # vdsmDebugPlugin.py should not exists
    try:
        import vdsmDebugPlugin
    except ImportError:
        # This is OK, it just means the file isn't
        # there and we are not running in debug mode.
        # Any other error is an error in the debug
        # plugin and we would like to print that out.
        pass

    log = logging.getLogger('vds')
    try:
        logging.root.handlers.append(logging.StreamHandler())
        log.handlers.append(logging.StreamHandler())

        pidfile = constants.P_VDSM_RUN + 'vdsmd.pid'
        file(pidfile, 'w').write(str(os.getpid()) + "\n")
        os.chmod(pidfile, 0664)

        sysname, nodename, release, version, machine = os.uname()
        log.info('I am the actual vdsm %s-%s %s (%s)',
                 dsaversion.software_version, dsaversion.software_revision,
                 nodename, release)
        serve_clients(log)
    except:
        log.error("Exception raised", exc_info=True)

    log.info("VDSM main thread ended. Waiting for %d other threads..." %
             (threading.activeCount() - 1))
    for t in threading.enumerate():
        if hasattr(t, 'stop'):
            t.stop()
        log.info(str(t))


def parse_args():
    opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
    for o, v in opts:
        o = o.lower()
        if o == "-h" or o == "--help":
            usage()
            sys.exit(0)

    if len(args) >= 1:
        usage()
        sys.exit(1)


def __assertVdsmUser():
    username = getpass.getuser()
    assert username == constants.VDSM_USER, (
        "VDSM failed to start: running user is not %s, trying "
        "to run from user %s" % (constants.VDSM_USER, username)
    )
    group = grp.getgrnam(constants.VDSM_GROUP)
    assert (constants.VDSM_USER in group.gr_mem or
            pwd.getpwnam(constants.VDSM_USER).pw_gid == group.gr_gid), \
        "VDSM failed to start: vdsm user is not in KVM group"

if __name__ == '__main__':
    __assertVdsmUser()
    os.setpgrp()
    parse_args()
    run()
